<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    //闭包是？
    //定义在一个函数内部的函数 . 函数嵌套函数。子函数可以调用父函数的变量 父函数不能使用子函数的变量
    //闭包函数就是外部函数被调用后，他的变量不会消失，仍然会被内部函数所使用，所有的内部函数都可以访问外部函数 

    //下面定义一个函数a  函数a里面还有个函数b
    //内部函数把自身参数m递加给外层函数变量n上  然后返回n的值
    //外部函数a的返回值为内部函数b  形成闭包
    function a(){         //外层函数  即父函数 。闭包函数
       var n = 0;         //私有变量
       function b(m){     //内部函数  即子函数
            n= n+m;       //递加上级私有变量的值 
            return n;     //返回改变后的值
       }
       return b;          //返回子函数
    }
    var b = a();          //调用父函数 返回子函数
    console.log(b(3))     //输出3
    console.log(b(3000))  //3003


// 示例2
    function foo () {     //外部函数foo  
    var a = 2
    function bar () {     //内部函数bar
        console.log(a)  
    }
        return bar        //抛出内部函数bar
    }
    var baz = foo()       //调用外部函数 返回内部函数
    baz() //2
    // 函数bar的词法作用域可以访问foo的内部作用域，并且bar在被作为返回值赋值给baz执行时，
    // bar函数在定义时的词法作用域以外的地方被调用，依然可以访问foo函数的内部作用域变量a，这就是闭包
    // 闭包可以访问到局部变量 

 //示例3   
    //闭包有两个作用，一个是可以访问到局部变量，另一个就是让这些变量的值始终保持在内存中
    //经典例子
    for (var i = 1; i <= 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 10)
    }
    //setTimeout是个异步函数，所以会先把循环全部执行完毕，这时候i就是6 了，所以会输出一堆6  用闭包解决
    for (var i = 1; i <= 5; i++) {
    (function(j) {
        setTimeout(function timer() {
            console.log(j);
        }, 10)
    })(i)
   }


//例子4
//闭包的定义很简单：函数 A 返回了一个函数 B，并且函数 B 中使用了函数 A 的变量，函数 B 就被称为闭包。
function A() {
  let a = 1
  function B() {
      console.log(a)
  }
  return B
}


// 形成闭包后，函数的执行空间不会被销毁，会一直存在。里面的变量也就不会被销毁。
/*
使用闭包主要是为了设计私有的方法和变量。
优点       是可以避免全局变量的污染；
缺点       是闭包会常驻内存，增加内存使用量，使用不当很容易造成内存泄漏。
在JavaScript中，函数即闭包，只有函数才会产生作用域闭包有3个特性
（1）函数嵌套函数。
（2）在函数内部可以引用外部的参数和变量
（3）参数和变量不会以垃圾回收机制回收
*/
  //闭包示例代码 
  var  func = (function(){
      var i = 1; 
      return function () {
            console.log(i) 
      }
  })()     
  
  



  
</script>